package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
)

func main() {

	// AES-128 key长度：16, 24, 32 bytes 对应 AES-128,AES-192,AES-256
	key := []byte("1234567890abcdef") //[]byte("1234567890abcdefghijklmnopqrstuv")
	//str := "区块链很有趣"
	//fmt.Println("------------AES 加密字节数组------------")
	//resultArr, _ := AesEncrypt([]byte(str), key)
	//fmt.Printf("加密后：%x\n", resultArr)
	//resultArr, _ = AesDecrypt(resultArr, key)
	//fmt.Println("解密后", string(resultArr))
	//fmt.Println("------------AES 加密字符串------------")
	//cipherText,	_ := AesEncryptString(str, key)
	//fmt.Println("加密后：", cipherText)
	cipherText := "Hsm2iXRl4gYwOYgVkxTYig=="
	originalText, _ := AesDecryptString(cipherText, key)
	fmt.Println("解密后：", originalText)

}

// AES 加密字节数组，返回字节数组
func AesEncrypt(originalBytes, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if nil != err {
		return nil, err
	}
	blockSize := block.BlockSize()
	originalBytes = PKCS5Padding(originalBytes, blockSize)
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	cipherArr := make([]byte, len(originalBytes))
	blockMode.CryptBlocks(cipherArr, originalBytes)
	return cipherArr, nil
}

// AES 加密文本，返回对加密后字节数组进行base64处理后字符串
func AesEncryptString(originalText string, key []byte) (string, error) {
	cipherBytes, err := AesEncrypt([]byte(originalText), key)
	if nil != err {
		return "", err
	}
	base64str := base64.StdEncoding.EncodeToString(cipherBytes)
	return base64str, nil
}

// AES 解密字节数组，返回字节数组
func AesDecrypt(cipherBytes, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if nil != err {
		return nil, err
	}
	blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	originalBytes := make([]byte, len(cipherBytes))
	blockMode.CryptBlocks(originalBytes, cipherBytes)
	originalBytes = PKCS5UnPadding(originalBytes)
	return originalBytes, nil
}

// 对 base64 处理后的加密文本进行 AES 解密，返回解密后明文
func AesDecryptString(cipherText string, key []byte) (string, error) {
	cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
	cipherBytes, err := AesDecrypt(cipherBytes, key)
	if nil != err {
		return "", err
	}
	//cipherBytes[len(cipherBytes)-1]=1
	return string(cipherBytes), nil
}

// 尾部填充
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}
